package com.sqsf.annotation;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;
@Component
@Aspect
//进一步标识当前类为切面类对象 需要先交由spring容器管理后才能生效
//使用当前切面类中的方法进行增强配置
//等价于 <aop:aspect ref="myAspect">
public class MyAspect {
    //通知注解
    //<aop:通知类型 method="方法" pointcut="切点表达式" 属性=值>
    //@通知类型(value="切点表达式",属性=值)
    //如果仅配置切点表达式可以省略value

    //切点表达的抽取
    //定义方法使用注解配置切点表达式 方法名就是切点表达式的id
    @Pointcut("execution(void com.sqsf.annotation.Target.select*(..))")
    public void select(){}{}
    //等价于 <aop:pointcut id="select" expression="execution(void com.sqsf.annotation.Target.select*(..))"/>

    @Pointcut("execution(int com.sqsf.annotation.Target.add(..))")
    public void add(){}
    //等价于 <aop:pointcut id="add" expression="execution(int com.sqsf.annotation.Target.add(..))"/>

    //在当前切面类中可以直接使用方法名() select() add() 进行使用
    //如果其他切面类需要使用 需要通过类名.方法名()  MyAspect.select() MyAspect.add() 进行使用



    //前置通知注解
    @Before("select()")
    //等价于<aop:before method="before" pointcut="execution(void com.sqsf.annotation.Target.select*(..))"/>
    public void before(){
        System.out.println("前置通知");
    }

    //后置通知注解
    @After("MyAspect.select()")
    //等价于<aop:after method="after" pointcut="execution(void com.sqsf.annotation.Target.select*(..))"/>
    public void after(){
        System.out.println("后置通知");
    }

    //环绕通知注解
    @Around("add()")
    //等价于<aop:around method="around" pointcut="execution(int com.sqsf.annotation.Target.add(..))"/>
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        System.out.println("环绕通知"+ Arrays.toString(args));
        Object proceed = joinPoint.proceed(args);
        System.out.println("环绕通知"+proceed);
        return proceed;
    }

    //异常通知注解
    @AfterThrowing(value ="MyAspect.add()",throwing = "e")
    //等价于<aop:after-throwing method="afterThrowing" throwing = "e" pointcut="execution(int com.sqsf.annotation.Target.add(..))"/>
    public void afterThrowing(Exception e){
        System.out.println("异常通知"+e);
    }

    //返回通知注解
    @AfterReturning(value = "add()",returning = "result")
    //等价于<aop:after-returning method="afterReturning" returning = "result" pointcut="execution(int com.sqsf.annotation.Target.add(..))"/>
    public void afterReturning(Object result){
        System.out.println("返回通知"+result);
    }

}
